package com.shadowlight.hero_story.cmdHandler;

import com.google.protobuf.GeneratedMessageV3;
import com.shadowlight.hero_story.util.PackageUtil;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Set;

/**
 * @Description handler工厂
 * @Author cz
 * @Date 2022/3/2
 */
@Slf4j
@SuppressWarnings("unchecked")
public final class HandlerFactory {
    private HandlerFactory() {
    }

    private static final HashMap<Class<?>, ICmdHandler<? extends GeneratedMessageV3>>
            HANDLER_FACTORY_MAP = new HashMap<>();

    public static void init() {
        Set<Class<?>> clzSet = PackageUtil.listSubClazz(ICmdHandler.class.getPackageName(), true, ICmdHandler.class);
        for (Class<?> clz : clzSet) {

            //判断clz不为抽象类
            if ((clz.getModifiers() & Modifier.ABSTRACT) != 0) {
                continue;
            }

            Method[] methods = clz.getDeclaredMethods();
            //消息类型
            Class<?> msgType = null;

            for (Method method : methods) {
                if (!method.getName().equalsIgnoreCase("handle")) {
                    continue;
                }

                Class<?>[] paraTypes = method.getParameterTypes();
                if (paraTypes.length < 2 || !GeneratedMessageV3.class.isAssignableFrom(paraTypes[1])
                        || GeneratedMessageV3.class == paraTypes[1]) {
                    continue;
                }

                msgType = paraTypes[1];
                //此处会把父类的handle方法也带进来，顺序是先自己的后父类的，所以在找到以后需要break退出查找
                break;
            }

            if (msgType == null) {
                continue;
            }

            try {
                ICmdHandler<?> newHandler = (ICmdHandler<?>) clz.getDeclaredConstructor().newInstance();
                HANDLER_FACTORY_MAP.put(msgType, newHandler);
                log.debug("{}<=========>{}", msgType.getName(), clz.getName());

            } catch (InstantiationException | InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
                log.error("转换出错: {}<===>{}", msgType.getName(), clz.getName());
                e.printStackTrace();
            }

        }

//        _handlerFactoryMap.put(GameMsgProtocol.UserLoginCmd.class, new UserLoginCmdHandler());
//        _handlerFactoryMap.put(GameMsgProtocol.SelectHeroCmd.class, new SelectHeroCmdHandler());
//        _handlerFactoryMap.put(GameMsgProtocol.UserEntryCmd.class, new UserEntryCmdHandler());
//        _handlerFactoryMap.put(GameMsgProtocol.WhoElseIsHereCmd.class, new WhoElseIsHereCmdHandler());
//        _handlerFactoryMap.put(GameMsgProtocol.UserMoveToCmd.class, new UserMoveToCmdHandler());
    }

    public static ICmdHandler<? extends GeneratedMessageV3> create(Class<?> msgClass) {
        if (msgClass == null) {
            return null;
        }
        return HANDLER_FACTORY_MAP.get(msgClass);
    }

}
